package com.gulimall.product.service.impl;


import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gulimall.common.constrant.ProductConstant;
import com.gulimall.common.to.*;
import com.gulimall.common.utils.PageUtils;
import com.gulimall.common.utils.Query;
import com.gulimall.common.utils.R;
import com.gulimall.product.dao.SpuInfoDao;
import com.gulimall.product.entity.*;
import com.gulimall.product.feign.CouponFeignService;
import com.gulimall.product.feign.SearchFeignService;
import com.gulimall.product.feign.WareFeignService;
import com.gulimall.product.service.*;
import com.gulimall.product.vo.SpuSaveVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {
    @Autowired
    private AttrService attrService;
    @Autowired
    private SpuInfoDescService infoDescService;
    @Autowired
    private SpuImagesService imagesService;
    @Autowired
    private ProductAttrValueService productAttrValueService;
    @Autowired
    private SkuInfoService skuInfoService;
    @Autowired
    private SkuImagesService skuImagesService;
    @Autowired
    private SkuSaleAttrValueServiceImpl skuSaleAttrValueService;
    @Autowired
    private BrandService brandService;
    @Autowired
    private CouponFeignService couponFeignService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private WareFeignService wareFeignService;
    @Autowired
    private SearchFeignService searchFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>());

        return new PageUtils(page);
    }

    @Override
    @Transactional
    public void saveSpuVo(SpuSaveVo spuSaveVo) {
        //1. 保存spu的基本信息 pms_spu_info
        SpuInfoEntity infoEntity = new SpuInfoEntity();
        BeanUtils.copyProperties(spuSaveVo, infoEntity);
        infoEntity.setCreateTime(new Date());
        infoEntity.setUpdateTime(new Date());
        saveSpuInfoVo(infoEntity);

        //2. 保存spu的描述图片 pms_spu_info_desc
        List<String> imageDecript = spuSaveVo.getDecript();
        SpuInfoDescEntity infoDescEntity = new SpuInfoDescEntity();
        infoDescEntity.setSpuId(infoEntity.getId());
        infoDescEntity.setDecript(String.join(",", imageDecript));
        infoDescService.saveImageDecript(infoDescEntity);

        //3. 保存spu的图片集  pms_spu_images
        List<String> saveVoImages = spuSaveVo.getImages();
        imagesService.saveSpuInfoImages(infoEntity.getId(), saveVoImages);

        //4. 保存spu的规格参数  pms_product_attr_value
        List<SpuSaveVo.BaseAttrsDTO> baseAttrsDTOS = spuSaveVo.getBaseAttrs();
        List<Long> attrIds = baseAttrsDTOS.stream().map(SpuSaveVo.BaseAttrsDTO::getAttrId).collect(Collectors.toList());
        List<AttrEntity> attrEntities = attrService.listByIds(attrIds);
        Map<Long, String> attrNameMap = new HashMap<>();
        attrEntities.forEach(item -> {
            attrNameMap.put(item.getAttrId(), item.getAttrName());
        });

        List<ProductAttrValueEntity> attrValueEntities = baseAttrsDTOS.stream().map(item -> {
            ProductAttrValueEntity attrValueEntity = new ProductAttrValueEntity();
            BeanUtils.copyProperties(item, attrValueEntity);
            attrValueEntity.setAttrName(attrNameMap.get(item.getAttrId()));
            attrValueEntity.setQuickShow(item.getShowDesc());
            attrValueEntity.setSpuId(infoEntity.getId());
            attrValueEntity.setAttrValue(item.getAttrValues());
            return attrValueEntity;
        }).collect(Collectors.toList());

        productAttrValueService.saveSpuProductAttr(attrValueEntities);

        //5. 保存spu的积分信息 sms_spu_bounds
        SpuSaveVo.BoundsDTO bounds = spuSaveVo.getBounds();
        SpuBoundsTo spuBoundsTo = new SpuBoundsTo();
        BeanUtils.copyProperties(bounds, spuBoundsTo);
        spuBoundsTo.setSpuId(infoEntity.getId());
        R res = couponFeignService.saveBounds(spuBoundsTo);
        if (res.getResult() != 0) {
            log.error("远程调用服务 /coupon/spubounds/save 发生错误");
        }

        //6. 保存sku信息
        //6.1 sku基本信息 pms_sku_info
        List<SpuSaveVo.SkusDTO> skusDTOList = spuSaveVo.getSkus();
        if (skusDTOList.size() > 0) {
            skusDTOList.forEach(item -> {
                R r = null;

                SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
                BeanUtils.copyProperties(item, skuInfoEntity);

                skuInfoEntity.setCatalogId(spuSaveVo.getCatalogId());
                skuInfoEntity.setBrandId(spuSaveVo.getBrandId());
                skuInfoEntity.setSpuId(infoEntity.getId());
                skuInfoEntity.setSaleCount(0L);
                skuInfoEntity.setSkuDesc("");

                List<SpuSaveVo.SkusDTO.ImagesDTO> itemImages = item.getImages();
                itemImages.forEach(images -> {
                    if (images.getDefaultImg() == 1) {
                        skuInfoEntity.setSkuDefaultImg(images.getImgUrl());
                    }
                });

                skuInfoService.saveSkuInfo(skuInfoEntity);

                List<SkuImagesEntity> skuImagesEntitys = itemImages.stream().map(images -> {
                    SkuImagesEntity imagesEntity = new SkuImagesEntity();
                    BeanUtils.copyProperties(images, imagesEntity);
                    imagesEntity.setSkuId(skuInfoEntity.getSkuId());
                    return imagesEntity;
                }).filter(entity -> {
                    return StringUtils.hasText(entity.getImgUrl());
                }).collect(Collectors.toList());

                //6.2 sku图片信息 pms_sku_images
                skuImagesService.saveSkuImage(skuImagesEntitys);

                List<SkuSaleAttrValueEntity> valueEntities = item.getAttr().stream().map(attr -> {
                    SkuSaleAttrValueEntity attrValueEntity = new SkuSaleAttrValueEntity();
                    BeanUtils.copyProperties(attr, attrValueEntity);
                    attrValueEntity.setSkuId(skuInfoEntity.getSkuId());
                    return attrValueEntity;
                }).collect(Collectors.toList());

                //6.3 sku销售属性信息 pms_sku_sale_attr_value
                skuSaleAttrValueService.saveBatchSaleAttr(valueEntities);

                //6.4 sku优惠 满减信息 会员优惠 sms_sku_ladder sms_sku_full_reduction sms_member_price
                //sku优惠
                SkuLadderTo ladderTo = new SkuLadderTo();
                ladderTo.setSkuId(skuInfoEntity.getSkuId());
                ladderTo.setAddOther(item.getCountStatus());
                ladderTo.setDiscount(item.getDiscount());
                ladderTo.setFullCount(item.getFullCount());
                ladderTo.setPrice(item.getDiscount().multiply(item.getPrice()));
                if (ladderTo.getFullCount() > 0) {
                    r = couponFeignService.saveSkuLadder(ladderTo);
                    if (r != null && r.getResult() != 0) {
                        log.error("远程调用服务 /coupon/spubounds/save 发生错误");
                    }
                }

                //满减信息
                SkuFullReductionTo fullReduction = new SkuFullReductionTo();
                fullReduction.setSkuId(skuInfoEntity.getSkuId());
                fullReduction.setFullPrice(item.getFullPrice());
                fullReduction.setReducePrice(item.getReducePrice());
                fullReduction.setAddOther(item.getPriceStatus());
                if (fullReduction.getFullPrice().compareTo(new BigDecimal(0)) > 0) {
                    r = couponFeignService.saveFullReduction(fullReduction);
                    if (r != null && res.getResult() != 0) {
                        log.error("远程调用服务 /coupon/spubounds/save 发生错误");
                    }
                }

                //会员优惠
                List<SpuSaveVo.SkusDTO.MemberPriceDTO> itemMemberPrice = item.getMemberPrice();
                List<SkuMemberPriceTo> skuMemberPriceTos = itemMemberPrice.stream().map(member -> {
                    SkuMemberPriceTo skuMemberPriceTo = new SkuMemberPriceTo();
                    skuMemberPriceTo.setSkuId(infoEntity.getId());
                    skuMemberPriceTo.setMemberLevelName(member.getName());
                    skuMemberPriceTo.setMemberPrice(member.getPrice());
                    skuMemberPriceTo.setMemberLevelId(member.getId());
                    skuMemberPriceTo.setAddOther(0);
                    return skuMemberPriceTo;
                }).filter(entity -> {
                    return entity.getMemberPrice().compareTo(new BigDecimal(0)) > 0;
                }).collect(Collectors.toList());

                r = couponFeignService.batchSaveMember(skuMemberPriceTos);
                if (r != null && r.getResult() != 0) {
                    log.error("远程调用服务 /coupon/spubounds/save 发生错误");
                }
            });
        }
    }

    public void saveSpuInfoVo(SpuInfoEntity infoEntity) {
        save(infoEntity);
    }

    @Override
    public PageUtils querySpuInfoByCondition(Map<String, Object> params) {
        QueryWrapper<SpuInfoEntity> queryWrapper = new QueryWrapper<>();

        String key = (String) params.get("key");
        if (StringUtils.hasText(key)) {
            queryWrapper.and(w -> {
                w.eq("id", key).or().like("spu_name", key);
            });
        }
        String status = (String) params.get("status");
        if (StringUtils.hasText(status)) {
            queryWrapper.eq("publish_status", status);
        }
        String brandId = (String) params.get("brandId");
        if (StringUtils.hasText(brandId) && !"0".equals(brandId)) {
            queryWrapper.eq("brand_id", brandId);
        }
        String catalogId = (String) params.get("catalogId");
        if (StringUtils.hasText(catalogId) && !"0".equals(catalogId)) {
            queryWrapper.eq("catalog_Id", catalogId);
        }

        IPage<SpuInfoEntity> iPage = this.page(new Query<SpuInfoEntity>().getPage(params), queryWrapper);
        return new PageUtils(iPage);
    }

    @Override
    public void upProduct(Long spuId) {
        SpuInfoEntity spuInfoEntity = getById(spuId);
        List<SkuInfoEntity> skuInfoEntityList = skuInfoService.list(new QueryWrapper<SkuInfoEntity>().eq("spu_id",
                spuId));
        BrandEntity brandEntity = brandService.getById(spuInfoEntity.getBrandId());
        CategoryEntity categoryEntity = categoryService.getById(spuInfoEntity.getCatalogId());

        //查出当前商品的可以被检索的属性
        List<ProductAttrValueEntity> attrValueEntities =
                productAttrValueService.list(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId));
        Set<Long> searchAttrId = attrService.getSearchAttrId(spuInfoEntity.getCatalogId());

        List<SkuEsModel.Attrs> attrsList =
                attrValueEntities.stream().filter(entity -> searchAttrId.contains(entity.getAttrId())).map(item -> {
                    SkuEsModel.Attrs attrs = new SkuEsModel.Attrs();
                    BeanUtils.copyProperties(item, attrs);
                    return attrs;
                }).collect(Collectors.toList());

        //查出所有规格商品的库存
        List<Long> skuIdList = skuInfoEntityList.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
        R result = wareFeignService.getStockBySkuId(skuIdList);
        Map<Long, Boolean> stockMap = new HashMap<>();
        if (result.getResult() == 0) {
            Map<Long, Boolean> stocks = (Map<Long, Boolean>) result.get("stocks");
            stockMap.putAll(stocks);
        } else {
            log.error("远程调用库存服务错误 ");
        }

        List<SkuEsModel> skuEsModels = skuInfoEntityList.stream().map(item -> {
            SkuEsModel skuEsModel = new SkuEsModel();
            BeanUtils.copyProperties(item, skuEsModel);

            skuEsModel.setSkuImg(item.getSkuDefaultImg());
            skuEsModel.setSkuPrice(item.getPrice());
            skuEsModel.setBrandName(brandEntity.getName());
            skuEsModel.setBrandImg(brandEntity.getLogo());
            skuEsModel.setCatalogId(categoryEntity.getCatId());
            skuEsModel.setCatalogName(categoryEntity.getName());
            skuEsModel.setHotScore(0L);

            List<SkuEsModel.Attrs> productAttrList = new ArrayList<>();
            productAttrList.addAll(attrsList);

            //查询当前规格属性
            List<SkuSaleAttrValueEntity> saleAttrValueEntities =
                    skuSaleAttrValueService.list(new QueryWrapper<SkuSaleAttrValueEntity>().eq("sku_id",
                            item.getSkuId()));

            saleAttrValueEntities.forEach(saleValue -> {
                SkuEsModel.Attrs attrs = new SkuEsModel.Attrs();
                BeanUtils.copyProperties(saleValue, attrs);
                productAttrList.add(attrs);
            });
            skuEsModel.setAttrs(productAttrList);
            skuEsModel.setHasStock(stockMap.get(item.getSkuId().toString()));

            return skuEsModel;
        }).collect(Collectors.toList());

        //调用远程服务将商品信息上传到es服务器上
        R r = searchFeignService.productUp(skuEsModels);
        if (r.getResult() == 0) {
            //修改成功将商品状态修改成已上架
            spuInfoEntity.setPublishStatus(ProductConstant.StatusEnum.SPU_UP.getCode());
            updateById(spuInfoEntity);
        } else {

        }
    }

    @Override
    public Map<String, String> findSpuBySkuIds(List<Long> skuIds) {
        List<SkuInfoEntity> skuInfoEntities = skuInfoService.listByIds(skuIds);
        Map<String, String> spuInfoMap = new HashMap<>();
        for (SkuInfoEntity skuInfoEntity : skuInfoEntities) {
            spuInfoMap.put(skuInfoEntity.getSkuId().toString(),
                    JSONObject.toJSONString(getById(skuInfoEntity.getSpuId())));
        }
        return spuInfoMap;
    }

}
